using System;
using System.Xml;

namespace Mbs.CastleContainer
{
    class DefaultElementProcessor : AbstractXmlNodeProcessor
    {
        private static readonly String IncludeAttrName = "includeUri";
        private static readonly DefaultTextNodeProcessor textProcessor = new DefaultTextNodeProcessor();
        private static readonly IncludeElementProcessor includeProcessor = new IncludeElementProcessor();

        public DefaultElementProcessor()
        {
        }

        public override String Name
        {
            get { return ""; }
        }

        public override void Process(IXmlProcessorNodeList nodeList, IXmlProcessorEngine engine)
        {
            XmlElement element = nodeList.Current as XmlElement;

            ProcessAttributes(element, engine);

            engine.DispatchProcessAll(new DefaultXmlProcessorNodeList(element.ChildNodes));
        }

        /// <summary>
        /// Processes element attributes.
        /// if the attribute is include will append to the element
        /// all contents from the file.
        /// if the attribute has a property reference the reference will be
        /// expanded
        /// </summary>
        /// <param name="element">The element.</param>
        private void ProcessAttributes(XmlElement element, IXmlProcessorEngine engine)
        {
            ProcessIncludeAttribute(element, engine);

            foreach (XmlAttribute att in element.Attributes)
            {
                textProcessor.ProcessString(att, att.Value, engine);
            }
        }

        private void ProcessIncludeAttribute(XmlElement element, IXmlProcessorEngine engine)
        {
            XmlAttribute include = element.Attributes[IncludeAttrName] as XmlAttribute;

            if (include != null)
            {
                // removing the include attribute from the element
                element.Attributes.RemoveNamedItem(IncludeAttrName);

                XmlNode includeContent = includeProcessor.ProcessInclude(element, include.Value, engine);

                if (includeContent != null)
                {
                    element.PrependChild(includeContent);
                }
            }
        }
    }
}
